/*
    Copyright (C) 1998-2004  Charles MacDonald

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "shared.h"

bitmap_t bitmap;
cart_t cart;                
input_t input;

static int iline_table[] = {0xC0, 0xE0, 0xF0};

/* Run the virtual console emulation for one frame */
void system_frame(int skip_render)
{
    int lpf = sms.display ? 313 : 262;
    int iline;

    /* Debounce pause key */
    if(input.system & INPUT_PAUSE)
    {
        if(!sms.paused)
        {
            sms.paused = 1;
            z80_set_irq_line(INPUT_LINE_NMI, ASSERT_LINE);
            z80_set_irq_line(INPUT_LINE_NMI, CLEAR_LINE);
        }
    }
    else
    {
         sms.paused = 0;
    }

    text_counter = 0;

    /* End of frame, parse sprites for line 0 on line 261 (VCount=$FF) */
    if(vdp.mode <= 7) parse_line(0);

    /* 3D glasses faking */
	if (sms.glasses_3d) skip_render = (sms.wram[0x1ffb] == 0) ? 1 : 0;

	for(vdp.line = 0; vdp.line < lpf;)
    {
        z80_execute(CYCLES_PER_LINE);

        iline = iline_table[vdp.extended];

        if(!skip_render)
        {
            render_line(vdp.line);
        }

        if(vdp.line <= iline)
        {
            vdp.left -= 1;
            if(vdp.left == -1)
            {
                vdp.left = vdp.reg[0x0A];
                vdp.hint_pending = 1;

                z80_execute(16);

                if(vdp.reg[0x00] & 0x10)
                {
                    z80_set_irq_line(0, ASSERT_LINE);
                }
            }
        }
        else
        {
            vdp.left = vdp.reg[0x0A];
        }

        if(vdp.line == iline)
        {
            vdp.status |= 0x80;
            vdp.vint_pending = 1;

            z80_execute(16);

            if(vdp.reg[0x01] & 0x20)
            {
                z80_set_irq_line(0, ASSERT_LINE);
            }
        }

        sound_update(vdp.line);

        ++vdp.line;

        if(vdp.mode <= 7) parse_line(vdp.line);
    }
}

void system_init(void)
{
	error_init();
    sms_init();
    pio_init();
    vdp_init();
    render_init();
    sound_init();
}

void system_shutdown(void)
{
    sms_shutdown();
    pio_shutdown();
    vdp_shutdown();
    render_shutdown();
    sound_shutdown();
    error_shutdown();
}

void system_reset(void)
{
    sms_reset();
    pio_reset();
    vdp_reset();
    render_reset();
    sound_reset();
    system_manage_sram(cart.sram, SLOT_CART, SRAM_LOAD);
}

void system_poweron(void)
{
    system_init();
	system_reset();
}

void system_poweroff(void)
{
    system_manage_sram(cart.sram, SLOT_CART, SRAM_SAVE);
}
